package tcp_app;

import java.awt.BorderLayout;


import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import java.net.*;
import java.io.*;
import java.util.*;

//Java Tcp: Client
public class Client {
	//程序开始的位置
	public static void main(String[] args) throws Exception{
		new OperSocket();
	}

}


//Tcp Client客户端处理的总工作台
class OperSocket{
	public static boolean flag = false;						//定义全局变量,客户端启动的总开关, 初始值为false,表示未开
	private Socket client;									//定义客户端
	private BufferedReader buf;								//定义客户端输入流
	private PrintStream out;								//定义客户端输出流
	private MyLoginWindows mlw;								//定义客户端登录窗口
	private ChatWindows cw;									//定义客户端聊天窗口
	private JTextArea jta_mess;								//定义客户端聊天记录文本框
	private JButton jbt_send;								//定义客户端聊天信息发送按钮
	private JTextField jtf_news;							//定义客户端聊天信息的文本框
	private String str;										//定义 str 接收服务器发送的信息
	private String name;									//定义 name 为客户端输入的 user name
	//通过构造方法, 开始运行
	public OperSocket() throws Exception{
		mlw = new MyLoginWindows();							//产生用户登录窗口
		while(!this.flag) {System.out.print("");}			//程序进入死循环, 等待用户登录
		this.client = new Socket("127.0.0.1", 8888);		//若登录成功, 输入连接服务器主机的ip地址(此127.0.0.1为测试ip)
        this.name = mlw.jtf_user.getText();					//对象的复制传输
		mlw.jf.dispose();									//关闭登录界面窗口
		cw = new ChatWindows(this.name);					//生成客户端聊天界面窗口
		this.jta_mess = cw.jta_mess;
		this.jbt_send = cw.jbt_send;
		this.jtf_news = cw.jtf_news;
		this.buf = new BufferedReader(new InputStreamReader(client.getInputStream()));		//获取此客户端的输入流
		this.out = new PrintStream(client.getOutputStream());								//得到此客户端的输出流
		jbt_send.addActionListener(new SendNews(this.out, this.jtf_news, this.jta_mess, this.name));	//为发送按钮增加监听器
		jtf_news.addKeyListener(new SendNews(this.out, this.jtf_news, this.jta_mess, this.name));	//为发送文本框增加键盘监听器
		//客户端进入死循环等待服务器发送的信息内容
		while(true) {
			str = this.buf.readLine();			//获取服务器发送的信息
			this.jta_mess.append(str + "\n");	//将信息添加到客户端聊天窗口的消息记录中
		}										
	}
}


//MyLoginWindows   定义客户端登录界面窗口类
//客户端登录界面窗口同服务器近似
class MyLoginWindows{
	JFrame jf;
	JButton jbt_lg;
	JButton jbt_ce;
	JLabel jlb_user;
	JLabel jlb_pass;
	JTextField jtf_user;
	JPasswordField jpf_pass;
	JPanel user;
	JPanel pass;
	JPanel button;
	Container con;
	public MyLoginWindows() {
		jf = new JFrame("Login Windows");
		
		jlb_user = new JLabel("User:");
		jlb_pass = new JLabel("Pass:");
		jtf_user = new JTextField(14);
		jtf_user.setText("your name:");				//设置客户端用户姓名提示
		jpf_pass = new JPasswordField(14);
		jbt_lg = new JButton("Login");
		jbt_ce = new JButton("Cancel");
		
		//增加事件监听器, 若用户点击登录, 则进行客户端启动开关为 true, 客户端启动
		jbt_lg.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				OperSocket.flag = true;
			}
		});
		
		//增加事件监听器, 若用户点击取消, 则退出程序
		jbt_ce.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		
		//对登录界面窗口组件布局进行设置
		
		con = jf.getContentPane();
		
		user = new JPanel();
		pass = new JPanel();
		button = new JPanel();
		
		con.add(user, BorderLayout.NORTH);
		con.add(pass, BorderLayout.CENTER);
		con.add(button, BorderLayout.SOUTH);
//		con.setBackground(Color.RED);
		
		user.add(jlb_user);
		user.add(jtf_user);
		pass.add(jlb_pass);
		pass.add(jpf_pass);
		button.add(jbt_lg);
		button.add(jbt_ce);
		
//		jf.pack();
		jf.setSize(360, 150);
		jf.setLocation(600, 280);
		jf.setVisible(true);
		jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
	}
}


//ChatWindows 为客户端 聊天界面窗口
//同服务器聊天界面窗口近似
class ChatWindows{
	JFrame jf;
	Container con;
	JPanel send;
	JPanel mess;
	JTextField jtf_news;
	JTextArea jta_mess;
	JScrollPane jsp;
	JButton jbt_send;
	Socket user;
	InetAddress inet;
	Scanner sc;
	BufferedReader buf;
	PrintStream out;
	String str;
	public ChatWindows(String s) throws Exception{
		
		jf = new JFrame(s);
		con = jf.getContentPane();
		jtf_news = new JTextField(s + "   is Login!", 14);
		jta_mess = new JTextArea(15, 25);
		jta_mess.setLineWrap(true);
		jsp = new JScrollPane(jta_mess, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		
        jta_mess.setEditable(false);
		jbt_send = new JButton("Send");
		mess = new JPanel();
		send = new JPanel();
		
		send.add(jtf_news);
		send.add(jbt_send);
		
		con.add(jsp, BorderLayout.CENTER);
		con.add(send, BorderLayout.SOUTH);
		
		jf.pack();
//		jf.setSize(280, 340);
		jf.setLocation(500, 260);
		jf.setVisible(true);
		jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
		
	}	
}


//定义按钮及键盘监听器类, 对客户端输入信息操作进行监听
class SendNews implements ActionListener, KeyListener{
	private JTextArea jta_mess;
	private JTextField jtf_news;
	private Socket user;
	private PrintStream out;
	private BufferedReader buf;
	private String str;
	private String name;
	public SendNews(PrintStream out, JTextField jtf_news, JTextArea jta_mess, String name) throws Exception{
		this.out = out;
		this.jta_mess = jta_mess;
		this.jtf_news = jtf_news;
		this.name = name;
	}
	//按钮事件的动作事件操作
	public void actionPerformed(ActionEvent e) {
		str = jtf_news.getText();						//获取客户端信息流内容
		out.println(this.name + ":  " + str + "");		//将此信息输出到服务器端
		jtf_news.setText("");							//客户端信息文本清空
	}
	//当用户在信息发送文本域   按回车键   的事件处理
	public void keyPressed(KeyEvent arg0) {
		if(arg0.getKeyCode() == KeyEvent.VK_ENTER){		//若事件源为键盘的回车
			str = jtf_news.getText();					//同上, 进行输出信息操作
			out.println(this.name + ":  " + str + "");
			jtf_news.setText("");
		}
	}
	public void keyReleased(KeyEvent arg0) {}
	public void keyTyped(KeyEvent arg0) {}
}